﻿using MongoDB.Driver;
using Sustainalytics.Auth.Claims;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Entities.RiskRatings;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.RiskRatings.Service.Controllers.Company
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/company/{companyId}")]
    public class MeiController : ApiController
    {
        private readonly IMongoCollection<RiskRatingMaterialEsgIssue> MEICollection;
        private readonly IMongoCollection<RiskRatingBenchmark> MEIBenchmarkCollection;
        private readonly IMongoCollection<CorporateData> _corporateDataCollection;
        private readonly IMongoCollection<CoreRiskRatingResearchProfile> _coreRiskRatingResearchProfile;

        public MeiController(
            IMongoCollection<CorporateData> corporateDataCollection,
            IMongoCollection<RiskRatingMaterialEsgIssue> MEICollection,
            IMongoCollection<RiskRatingBenchmark> MEIBenchmarkCollection,
        IMongoCollection<CoreRiskRatingResearchProfile> coreRiskRatingResearchProfile)
        {
            this.MEICollection = MEICollection;
            this.MEIBenchmarkCollection = MEIBenchmarkCollection;
            _corporateDataCollection = corporateDataCollection;
            _coreRiskRatingResearchProfile = coreRiskRatingResearchProfile;
        }

        [HttpGet]
        [Route("mei/{externalId}")]
        [InjectUniverse("universeIds", AccountFeature.RiskRatingsResearch)]
        public async Task<HttpResponseMessage> GetMeiInfo(Guid companyId, int externalId, [FromUri]int[] universeIds = null)
        {
            var corpData = await _corporateDataCollection.Find(
                Builders<CorporateData>.Filter.And(
                    Builders<CorporateData>.Filter.Eq(x => x.Id, companyId),
                    Builders<CorporateData>.Filter.AnyIn(x => x.UniverseIds, universeIds)))
                    .FirstOrDefaultAsync().ConfigureAwait(false);

            if (corpData == null)
                return Request.CreateResponse(HttpStatusCode.Unauthorized);

            var mei = await MEICollection.Find(x => x.CompanyId == companyId && x.ExternalId == externalId).FirstOrDefaultAsync().ConfigureAwait(false);
            var meiBenchmark = await MEIBenchmarkCollection.Find(y => y.Id == companyId).FirstOrDefaultAsync().ConfigureAwait(false);
            var result = new
            {
                mei.ExternalId,
                mei.Name,
                Type = mei.Type.ToString(),
                IsMain = mei.IsMain.Value,
                AssessmentCode = mei.Cluster.Code,
                RiskRating = mei.ManagementRisk.UnmanagedRisk.Value,
                ManagedRisk = mei.ManagementRisk.ManagedRisk.Value,
                UnmanagedRisk = mei.ManagementRisk.UnmanagedRisk.Value,
                Exposure = mei.ManagementRisk.Exposure.Value,
                ManageableRisk = mei.ManagementRisk.ManageableRisk.Value,
                Management = mei.ManagementRisk.Management.Value,
                SubindustryExposureScore = mei.SubIndustryExposureScore.Value,
                ExcessExposure = (mei.FinalBetaFactor?.Value - 1) * 100,
                ManageableRiskFactorPercentile = mei.ManageableRiskFactorPercentile.Value,
                SubIndustryAverageExposure = meiBenchmark.MaterialEsgIssueBenchmarks.Count(x => x.MeiExternalId == externalId)>0? meiBenchmark.MaterialEsgIssueBenchmarks.First(x => x.MeiExternalId == externalId).SubIndustryPerformanceExposure.Average:0,
                SubIndustryAverageManagement= meiBenchmark.MaterialEsgIssueBenchmarks.Count(x => x.MeiExternalId == externalId) > 0 ? meiBenchmark.MaterialEsgIssueBenchmarks.First(x => x.MeiExternalId == externalId).SubIndustryPerformanceManagement.Average : 0,
                Comments = new
                {
                    Management = mei.ManagementComment?.Value,
                    Exposure = mei.ExposureComment?.Value,
                    AnalystViewExposureAssessment = mei.AnalystViewExposureAssessment?.Value,
                    Analyst = mei.AnalystViewComment?.Value,
                    AnalystViewManagementAssessment = mei.AnalystViewManagementAssessment?.Value
                },
                Narrative = mei.Narrative.Value,
                FinalWeight = mei.FinalWeight.Value,
                BetaFactor = mei.BetaFactor.Value,
                FinalBetaFactor = mei.FinalBetaFactor?.Value,
                Indicators =
                mei.Type == MaterialIssueType.BaselineIssue ?
                mei.Indicators.OrderBy(x => x.SortKey.Value).Select(CreateIndicator()) :
                mei.Indicators.OrderBy(x => x.IndicatorType).ThenByDescending(x => x.AnswerCategory.Value).ThenBy(x => x.Name).Select(CreateIndicator())
            };

            return Request.CreateResponse(HttpStatusCode.OK, result);
        }

        [HttpGet]
        [Route("indentPercentile")]
        [InjectUniverse("universeIds", AccountFeature.RiskRatingsResearch)]
        public async Task<HttpResponseMessage> GetCoreIndentPercentile(Guid companyId, [FromUri]int[] universeIds = null)
        {
            var researchProfile = _coreRiskRatingResearchProfile.Find(x => x.Id == companyId).FirstOrDefault();
            return Request.CreateResponse(HttpStatusCode.OK, researchProfile.IndentPercentile?.Value);
        }

        private static Func<ComprehensiveRiskRatingIndicator, object> CreateIndicator()
        {
            return indicator => new
            {
                indicator.Name,
                indicator.IndicatorType,
                Code = indicator.Code.Replace('.', '_'),
                RawScore = indicator.RawScore.Value,
                FinalWeight = indicator.FinalWeight.Value,
                WeightedScore = indicator.WeightedScore.Value,
                WeightInMei = indicator.WeightInMei?.Value,
                WeightedScoreInMei = indicator.WeightedScoreInMei?.Value,
                Category = indicator.AnswerCategory.Value
            };
        }
    }
}
